/*
 *  $Id: Graveyard.cs 1195 2010-11-19 15:17:06Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;
using System.Collections;
using System.Collections.Generic;

namespace Ragima {
    /// <summary>
    /// Могильник: список мертвых существ
    /// </summary>
    public class Graveyard: List<GraveyardItem> {
        public void Add(Creature creature) {
            Add(new GraveyardItem(creature));
        }

        public void MoveTo(GraveyardItem item, GameCardDeck destination) {
            if (Contains(item)) {
                destination.Add(item.Card);
                Remove(item);
            }
        }
        public void MoveTo(IEnumerable<GraveyardItem> items, GameCardDeck destination) {
            foreach (GraveyardItem item in items)
                MoveTo(item, destination);
        }
        public void MoveTo(int count, GameCardDeck destination) {
            count = Math.Min(count, Count);
            if (count <= 0) return;
            for (int i = 0; i < count; i++) destination.Add(this[i].Card);
            RemoveRange(0, count);
        }
        public void MoveTo(GameCardDeck destination) {
            foreach (GraveyardItem item in this) destination.Add(item.Card);
            Clear();
        }

        public GraveyardItem GetUndying() {
            int max = Count-1;
            for (int i = max; i >= 0; i--) {
                GraveyardItem item = this[i];
                if (item.CanResurrect && item.CanUndying(max - i) && !item.Antimagic)
                    return item;
            }
            return null;
        }

        public List<GraveyardItem> GetItemsWithoutAntimagic(int count) {
            List<GraveyardItem> list = new List<GraveyardItem>();
            foreach (GraveyardItem item in this) {
                if (!item.AntimagicArea) {
                    list.Add(item);
                    if (count > 0 && list.Count >= count)
                        break;
                }
            }
            return list;
        }
    }

    /// <summary>
    /// Элемент могильника, представляющий собой карту, флаг "нежить", и значение неупокоенности.
    /// Так же хранит список эффектов, которые должны сохраняться в могильнике.
    /// </summary>
    public class GraveyardItem {
        private const int NotUndying = -1;

        public readonly CreatureCard Card;
        private int _modDamage, _modHealth;
        private bool _undead, _antimagic, _antimagicArea;
        private int _undying;
        private List<Affect> _affects;

        public GraveyardItem(Creature creature) {
            Card = creature.Card;
            _modDamage = creature.Summary.GetDamage();
            _modHealth = creature.Summary.GetMaxHealth();
            _undead = creature.IsUndead;
            _undying = creature.Summary.Undying.Empty ? NotUndying : creature.Summary.Undying.Current.Value;
            _antimagic = creature.HasFlag<Affects.GraveyardAntimagic>();
            _antimagicArea = creature.HasFlag<Affects.GraveyardAntimagicArea>();
            _affects = new List<Affect>();
            foreach (Affect affect in creature.GetAffects(false, NeedForGraveyard))
                _affects.Add(affect.Clone());
        }

        public int Damage {
            get { return Math.Max(Card.Damage + _modDamage, 0); }
        }
        public int Health {
            get { return Math.Max(Card.Health + _modHealth, 0); }
        }

        public bool Antimagic {
            get { return _antimagic; }
        }
        public bool AntimagicArea {
            get { return _antimagicArea; }
        }

        public bool CanResurrect {
            get { return Health > 0; }
        }

        public bool Undead {
            get { return _undead; }
        }

        public bool IsUndying {
            get { return _undying >= 0; }
        }

        public bool CanUndying(int pos) {
            return IsUndying && _undying <= pos;
        }

        public void RestoreCreature(Creature creature) {
            creature.Summary.ChangeDamage(_modDamage);
            creature.Summary.ChangeMaxHealth(_modHealth);
            if (_undead && !creature.IsUndead)
                creature.AddAffect<Affects.Undead>();
            if (IsUndying)
                creature.AddAffect(new Affects.Undying(_undying));
            foreach (Affect affect in _affects) creature.AddAffect(affect);
        }

        private static bool NeedForGraveyard(Affect affect) {
            return affect is GraveyardEnchantmentAffect;
        }
    }

}